package org.csu.mybigpro.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.csu.mybigpro.DTO.*;
import org.csu.mybigpro.common.CommonResponse;
import org.csu.mybigpro.domain.Replies;
import org.csu.mybigpro.domain.Threads;
import org.csu.mybigpro.domain.ThumbsUp;
import org.csu.mybigpro.persistence.RepliesMapper;
import org.csu.mybigpro.persistence.ThreadsMapper;
import org.csu.mybigpro.persistence.ThumbsUpMapper;
import org.csu.mybigpro.persistence.UserMapper;
import org.csu.mybigpro.service.ForumService;
import org.jsoup.Jsoup;
import org.jsoup.safety.Safelist;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ForumServiceImpl implements ForumService {

    @Autowired
    private ThreadsMapper threadsMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RepliesMapper repliesMapper;

    @Autowired
    private ThumbsUpMapper thumbsUpMapper;

    @Override
    public CommonResponse<GetThreadsRspVO> getThreads(GetThreadsReqVO reqVO) {

        int pageNo = reqVO.getPageNo();
        int pageSize = reqVO.getPageSize();
        String searchKey = reqVO.getSearchKey();
        String sortBy = reqVO.getSortBy();



        Page<Threads> threadsPage = threadsMapper.selectPageList(pageNo, pageSize, searchKey, sortBy);
        Long total = (long) threadsMapper.threadsCount();
        List<Threads> threads = threadsPage.getRecords();

        GetThreadsRspVO rspVO = null;

        if (total > 0 && !CollectionUtils.isEmpty(threads)) {
            rspVO = GetThreadsRspVO.builder()
                    .total(Math.toIntExact(total))
                    .threads(
                            threads.stream()
                                    .map(thread -> GetThreadsRspVO.GetThread.builder()
                                            .id(thread.getId())
                                            .title(thread.getTitle())
                                            .authorId(thread.getAuthorId())
                                            .content(thread.getContent())
                                            .authorName(userMapper.selectById(thread.getAuthorId()).getName())
                                            .authorAvatar(userMapper.selectById(thread.getAuthorId()).getAvatarUrl())
                                            .replyCount(thread.getReplyCount())
                                            .viewCount(thread.getViewCount())
                                            .isPinned(thread.getIsPinned())
                                            .createdAt(thread.getCreatedAt())
                                            .lastReplyAt(thread.getLastReplyAt())
                                            .build())
                                    .collect(Collectors.toList())
                    )
                    .build();

        }

        return CommonResponse.createForSuccess(rspVO);
    }

    @Override
    public CommonResponse<GetThreadByIdRspVO> getThreadsById(GetThreadByIdReqVO reqVO) {

        Long threadId = reqVO.getThreadId();
        int pageNo = reqVO.getPageNo();
        int pageSize = reqVO.getPageSize();

        Page<Replies> repliesPage= repliesMapper.selectPageList(threadId,pageNo,pageSize);
        int total = repliesMapper.selectCountByThreadId(threadId);
        List<Replies> repliesPageRecords = repliesPage.getRecords();

        Threads threads = threadsMapper.selectById(threadId);

        GetThreadByIdRspVO rspVO = null;

        if(threads != null) {
            rspVO = GetThreadByIdRspVO.builder()
                    .id(threads.getId())
                    .title(threads.getTitle())
                    .authorId(threads.getAuthorId())
                    .authorName(userMapper.selectById(threads.getAuthorId()).getName())
                    .createdAt(threads.getCreatedAt())
                    .content(threads.getContent())
                    .authorAvatar(userMapper.selectById(threads.getAuthorId()).getAvatarUrl())
                    .repliesTotal(total)
                    .repliesList(
                            repliesPageRecords.stream()
                                    .map(replies -> GetThreadByIdRspVO.Replies.builder()
                                            .id(replies.getId())
                                            .content(replies.getContent())
                                            .authorId(replies.getAuthorId())
                                            .authorName(userMapper.selectById(replies.getAuthorId()).getName())
                                            .createdAt(replies.getCreatedAt())
                                            .thumbsUpCount(replies.getThumbsUpCount())
                                            .authorAvatar(userMapper.selectById(replies.getAuthorId()).getAvatarUrl())
                                            .build())
                                    .collect(Collectors.toList())
                    )
                    .build();
        }


        return CommonResponse.createForSuccess(rspVO);
    }

    @Override
    public CommonResponse<CreateThreadRspVO> createThread(String teacherId, CreateThreadReqVO reqVO) {

        String content = reqVO.getContent();
        String title = reqVO.getTitle();

        Threads insertThread =Threads.builder()
                .authorId(Long.valueOf(teacherId))
                .title(title)
                .content(content)
                .viewCount(0)
                .replyCount(0)
                .isPinned(false)
                .lastReplyAt(LocalDateTime.now())
                .isDelete("0")
                .build();

        int insert = threadsMapper.insert(insertThread);

        if(insert > 0) {
            Long newId = insertThread.getId();
            CreateThreadRspVO rspVO = CreateThreadRspVO.builder()
                    .threadId(newId)
                    .build();
            return CommonResponse.createForSuccess(rspVO);
        }

        return CommonResponse.createForError();
    }

    @Override
    public CommonResponse<CreateReplyRspVO> createReply(String teacherId, CreateReplyReqVO reqVO) {
        Long threadId = reqVO.getThreadId();
        String content = reqVO.getContent();

        // 关键步骤：清理HTML内容
        content = sanitizeHtml(content);

        Replies insertReplies = Replies.builder()
                .authorId(Long.valueOf(teacherId))
                .content(content)
                .threadId(threadId)
                .thumbsUpCount(0)
                .isDelete("0")
                .build();

        int insert = repliesMapper.insert(insertReplies);
        if(insert > 0) {
            //更新另一个表的内容
            int row = threadsMapper.updateReplyTimeAndCount(threadId);
            if(row > 0){
                Long newId = insertReplies.getId();
                CreateReplyRspVO rspVO = CreateReplyRspVO.builder()
                        .replyId(newId)
                        .build();
                return CommonResponse.createForSuccess(rspVO);
            }
        }

        return CommonResponse.createForError();
    }

    @Override
    public CommonResponse<AddReadRspVO> addRead(String teacherId, AddReadReqVO reqVO) {
        int threadId = reqVO.getThreadId();

        int row = threadsMapper.updateView(threadId);

        if(row > 0){

            AddReadRspVO rspVO = AddReadRspVO.builder().build();

            return CommonResponse.createForSuccess();
        }

        return CommonResponse.createForError();
    }

    @Override
    public CommonResponse<ThumbsUpRspVO> thumbsUp(String teacherId, ThumbsUpReqVO reqVO) {
        int replyId = reqVO.getReplyId();

        //是否存在
        ThumbsUp thumbsUp1 = thumbsUpMapper.searchByteacherIdAndReplyId(replyId, teacherId);

        if(thumbsUp1 != null){
            //已经存在点赞
            if("1".equals(thumbsUp1.getThumbsUp())){
                ThumbsUpRspVO rspVO = ThumbsUpRspVO.builder()
                        .msg("已经存在点赞")
                        .build();
                return CommonResponse.createForSuccess(rspVO);
            }else{
                int row = thumbsUpMapper.thumbsUp(teacherId,replyId);
                if(row > 0) {
                    ThumbsUpRspVO rspVO = ThumbsUpRspVO.builder()
                            .msg("点赞成功")
                            .build();
                    row = repliesMapper.thumbsUp(replyId);
                    if(row > 0){
                        return CommonResponse.createForSuccess(rspVO);
                    }else {
                        //第二个表添加错误，但是按道理不会执行到这里
                        System.out.println("添加错误");
                        return CommonResponse.createForError();
                    }
                }else {
                    //理论上不会运行到这里吧
                    //点赞错误
                    return CommonResponse.createForError();
                }
            }

        }else {
            ThumbsUp thumbsUp = ThumbsUp.builder()
                    .userId(Long.valueOf(teacherId))
                    .replyId((long) replyId)
                    .thumbsUp("1")
                    .build();
            int insert = thumbsUpMapper.insert(thumbsUp);
            if(insert > 0){
                //点赞成功
                ThumbsUpRspVO rspVO = ThumbsUpRspVO.builder()
                        .msg("点赞成功")
                        .build();
                //更改另一个表
                int row = repliesMapper.thumbsUp(replyId);
                if(row > 0){
                    return CommonResponse.createForSuccess(rspVO);
                }else {
                    //第二个表添加错误，但是按道理不会执行到这里
                    System.out.println("添加错误");
                    return CommonResponse.createForError();
                }
            }else {
                //点赞失败，但是不知道什么原因，按可能数据库冲突
                return CommonResponse.createForError();
            }
        }


    }

    @Override
    public CommonResponse<ThumbsDownRspVO> thumbsDown(String teacherId, ThumbsDownReqVO reqVO) {
        int replyId = reqVO.getReplyId();

        //是否存在
        ThumbsUp thumbsUp1 = thumbsUpMapper.searchByteacherIdAndReplyId(replyId, teacherId);
        if(thumbsUp1 != null){


            int row = thumbsUpMapper.thumbsDown(teacherId,replyId);

            if(row > 0 && "1".equals(thumbsUp1.getThumbsUp())){
                //取消点赞成功
                //更改另一个表
                int rowOther = repliesMapper.thumbsDown(replyId);
                if(rowOther > 0 ){
                    ThumbsDownRspVO rspVO = ThumbsDownRspVO.builder()
                            .msg("取消点赞成功")
                            .build();
                    return CommonResponse.createForSuccess(rspVO);

                }else {
                    return CommonResponse.createForError();
                }

            }else if (row > 0 && "0".equals(thumbsUp1.getThumbsUp())){
                //原本就是取消点赞状态
                ThumbsDownRspVO rspVO = ThumbsDownRspVO.builder()
                        .msg("已经点踩")
                        .build();
                return CommonResponse.createForSuccess(rspVO);
            }else {

                return CommonResponse.createForError();
            }

        }else {
            //并没有存在点赞
            //只是点了个踩

            ThumbsUp thumbsUp = ThumbsUp.builder()
                    .userId(Long.valueOf(teacherId))
                    .replyId((long) replyId)
                    .thumbsUp("0")
                    .build();
            int insert = thumbsUpMapper.insert(thumbsUp);
            if(insert > 0){
                //点踩成功
                ThumbsDownRspVO rspVO = ThumbsDownRspVO.builder()
                        .msg("点踩成功")
                        .build();
                return CommonResponse.createForSuccess(rspVO);

            }else {
                //点赞失败，但是不知道什么原因，按可能数据库冲突
                return CommonResponse.createForError();
            }
        }

    }

    @Override
    public CommonResponse<DelReplyRspVO> DelReply(String teacherId, DelReplyReqVO reqVO) {
        int replyId = reqVO.getReplyId();

        Replies replies = repliesMapper.getRepliesById(replyId);

        if(replies != null){
            //找到了这个id
            if("0".equals(replies.getIsDelete())){
                //还存在着
                String repliesAuthorId = String.valueOf(replies.getAuthorId());
                String threadAuthorId = String.valueOf(threadsMapper.getByThreadId(replies.getThreadId()).getAuthorId());
                if(teacherId.equals(repliesAuthorId) || threadAuthorId.equals(teacherId)){
                    int row = repliesMapper.delReply(replyId);
                    if(row > 0){
                        DelReplyRspVO rspVO = DelReplyRspVO.builder()
                                .msg("删除成功")
                                .build();
                        return CommonResponse.createForSuccess(rspVO);
                    }else {
                        return CommonResponse.createForError();
                    }

                }else {
                    DelReplyRspVO rspVO = DelReplyRspVO.builder()
                            .msg("删除失败，请勿尝试删除他人的回复")
                            .build();
                    return CommonResponse.createForSuccess(rspVO);
                }

            }else {
                //早删了
                DelReplyRspVO rspVO = DelReplyRspVO.builder()
                        .msg("已删除")
                        .build();
                return CommonResponse.createForSuccess(rspVO);
            }
        }else {
            //没有找到这个id
            return CommonResponse.createForError();
        }

    }

    /**
     * 清理HTML内容，防止XSS攻击
     * @param html 原始HTML字符串
     * @return 清理后的安全HTML字符串
     */
    private String sanitizeHtml(String html) {
        if (html == null) {
            return null;
        }
        // 使用 basicWithImages 作为基础，它已经包含了 img, a, p, br 等标签
        Safelist safelist = Safelist.basicWithImages();

        // 允许 img 标签拥有 style, width, height, alt 属性
        safelist.addAttributes("img", "style", "width", "height", "alt");

        // **【关键修改】** 允许 a 标签拥有 target 和 download 属性
        // href 属性已在 basic() 中默认包含
        safelist.addAttributes("a", "target", "download");

        // 配置 a 标签的协议，允许 http, https, 和 mailto
        safelist.addProtocols("a", "href", "http", "https", "mailto");

        // 执行清理
        String sanitized = Jsoup.clean(html, safelist);
        return sanitized;
    }

}
